use clap::{Parser, Subcommand, ValueEnum};
use std::path::PathBuf;
use std::time::Instant;
use pipit_core::pipit_stdlib_integration;

#[cfg(feature = "jit")]
use pipit_core::jit::integration::JITContext;
use pipit_core::vm::{VirtualMachine, Instruction};
use pipit_core::compiler::Compiler;
use pipit_core::Value;

/// Pipit JIT编译器CLI
#[derive(Parser)]
#[command(name = "pipit")]
#[command(version = "1.0.0")]
struct Cli {
    #[command(subcommand)]
    command: Commands,
    
    /// 启用详细输出
    #[arg(short, long, global = true)]
    verbose: bool,
    
    /// 优化级别
    #[arg(short, long, global = true, default_value = "aggressive")]
    optimization: OptimizationLevelArg,
    
    /// 禁用JIT，使用解释器
    #[arg(long, global = true)]
    no_jit: bool,
}

#[derive(Subcommand)]
enum Commands {
    /// 运行Pipit脚本
    Run {
        /// 脚本文件路径
        file: PathBuf,
        
        /// 传递给脚本的参数
        args: Vec<String>,
    },
    
    /// 编译Pipit脚本到机器码
    Compile {
        /// 输入文件
        input: PathBuf,
        
        /// 输出文件
        output: Option<PathBuf>,
    },
    

    
    /// JIT调试
    Debug {
        /// 调试文件
        file: PathBuf,
    },
    
    /// 调试并发引擎
    DebugConcurrent,
}

#[derive(ValueEnum, Clone, Copy, Debug)]
enum OptimizationLevelArg {
    None,
    Basic,
    Aggressive,
}

#[cfg(feature = "jit")]
impl From<OptimizationLevelArg> for pipit_core::jit::JITOptimizationLevel {
    fn from(level: OptimizationLevelArg) -> Self {
        match level {
            OptimizationLevelArg::None => pipit_core::jit::JITOptimizationLevel::None,
            OptimizationLevelArg::Basic => pipit_core::jit::JITOptimizationLevel::Basic,
            OptimizationLevelArg::Aggressive => pipit_core::jit::JITOptimizationLevel::Aggressive,
        }
    }
}

fn main() {
    let cli = Cli::parse();
    
    match cli.command {
        Commands::Run { file, args } => {
            run_script(&file, &args, !cli.no_jit, cli.optimization, cli.verbose);
        }
        Commands::Compile { input, output } => {
            compile_script(&input, output.as_ref(), !cli.no_jit, cli.verbose);
        }

        Commands::Debug { file } => {
            debug_script(&file, cli.verbose);
        }
        Commands::DebugConcurrent => {
            debug_concurrent_engine();
        }
    }
}

/// 运行Pipit脚本 - 不依赖JIT的版本
fn run_script(file: &PathBuf, _args: &[String], _use_jit: bool, _optimization: OptimizationLevelArg, verbose: bool) {
    let start = Instant::now();
    
    let content = std::fs::read_to_string(file)
        .expect("无法读取文件");
    
    if verbose {
        println!("正在执行: {}", file.display());
        println!("使用解释器执行（不依赖JIT）");
    }
    
    // 使用编译器编译源代码
    let mut compiler = Compiler::new();
    let bytecode = match compiler.compile(&content) {
        Ok(bytecode) => {
            // 保存字节码到文件，用于调试
            let bytecode_path = file.with_extension("bytecode");
            if let Err(err) = std::fs::write(&bytecode_path, format!("{:?}", bytecode)) {
                eprintln!("警告：无法保存字节码到 {}: {:?}", bytecode_path.display(), err);
            } else if verbose {
                println!("字节码已保存到: {}", bytecode_path.display());
                println!("字节码内容: {:?}", bytecode);
            }
            bytecode
        },
        Err(e) => {
            eprintln!("编译错误: {:?}", e);
            std::process::exit(1);
        }
    };
    
    let mut vm = VirtualMachine::new();
    // 注册标准库函数
    pipit_stdlib_integration::register_stdlib_functions(&mut vm);
    
    // 注册编译器生成的函数
    for (_, (address, param_count)) in compiler.get_functions() {
        vm.register_function(*address, *param_count);
    }
    
    vm.load_bytecode(bytecode);
    
    // 移除所有JIT相关的代码，只使用解释器执行
    let result = vm.execute();
    let duration = start.elapsed();
    
    if verbose {
        println!("执行结果: {:?}", result);
        println!("执行时间: {:?}", duration);
    } else {
        println!("{:?}", result);
    }
}

/// 编译脚本 - 完全不依赖JIT的版本
fn compile_script(input: &PathBuf, output: Option<&PathBuf>, _use_jit: bool, verbose: bool) {
    let content = std::fs::read_to_string(input)
        .expect("无法读取输入文件");
    
    // 确定输出文件路径，默认使用当前目录
    let output_path = match output {
        Some(path) => path.to_path_buf(),
        None => {
            let file_name = input.file_stem().unwrap_or_default().to_str().unwrap_or_default();
            PathBuf::from(format!("{}.bytecode", file_name))
        }
    };
    
    // 创建编译器并编译源代码
    let mut compiler = Compiler::new();
    match compiler.compile(&content) {
        Ok(bytecode) => {
            // 直接将字节码的字符串表示写入文件（不依赖序列化）
            let bytecode_str = format!("{:?}", bytecode);
            std::fs::write(&output_path, &bytecode_str)
                .expect("无法写入字节码文件");
            
            println!("编译完成: {}", input.display());
            println!("输出文件: {}", output_path.display());
            
            if verbose {
                println!("生成了 {} 条指令", bytecode.len());
                println!("字节码内容: {}", bytecode_str);
            }
        },
        Err(err) => {
            eprintln!("编译错误: {:?}", err);
            std::process::exit(1);
        }
    }
}



/// 序列化字节码以便存储到文件
fn serialize_bytecode_for_storage(bytecode: &[Instruction]) -> Vec<u8> {
    let mut serialized = Vec::new();
    
    // 写入指令数量
    serialized.extend_from_slice(&(bytecode.len() as u32).to_le_bytes());
    
    // 写入每条指令
    for instr in bytecode {
        match instr {
            Instruction::Push(value) => {
                serialized.push(0x01); // Push操作码
                
                // 序列化不同类型的值
                match value {
                    Value::Null => {
                        serialized.push(0x00); // Null类型标记
                    },
                    Value::Boolean(b) => {
                        serialized.push(0x01); // Boolean类型标记
                        serialized.push(if *b { 0x01 } else { 0x00 });
                    },
                    Value::Integer(i) => {
                        serialized.push(0x02); // Integer类型标记
                        serialized.extend_from_slice(&i.to_le_bytes());
                    },
                    Value::Float(f) => {
                        serialized.push(0x03); // Float类型标记
                        serialized.extend_from_slice(&f.to_le_bytes());
                    },
                    Value::String(s) => {
                        serialized.push(0x04); // String类型标记
                        let len_bytes = (s.len() as u32).to_le_bytes();
                        serialized.extend_from_slice(&len_bytes);
                        serialized.extend_from_slice(s.as_bytes());
                    },
                    _ => {
                        // 处理其他类型
                        serialized.push(0xFF); // 未知类型标记
                    }
                }
            },
            Instruction::Add => serialized.push(0x10),
            Instruction::Sub => serialized.push(0x11),
            Instruction::Mul => serialized.push(0x12),
            Instruction::Div => serialized.push(0x13),
            Instruction::Mod => serialized.push(0x14),
            Instruction::Pow => serialized.push(0x15),
            Instruction::Equal => serialized.push(0x20),
            Instruction::LessThan => serialized.push(0x21),
            Instruction::GreaterThan => serialized.push(0x22),
            Instruction::And => serialized.push(0x30),
            Instruction::Or => serialized.push(0x31),
            Instruction::Not => serialized.push(0x32),
            Instruction::Jump(offset) => {
                serialized.push(0x40);
                serialized.extend_from_slice(&(*offset as u32).to_le_bytes());
            },
            Instruction::JumpIfFalse(offset) => {
                serialized.push(0x41);
                serialized.extend_from_slice(&(*offset as u32).to_le_bytes());
            },
            Instruction::JumpIfTrue(offset) => {
                serialized.push(0x42);
                serialized.extend_from_slice(&(*offset as u32).to_le_bytes());
            },
            Instruction::Call(idx) => {
                serialized.push(0x50);
                serialized.extend_from_slice(&(*idx as u32).to_le_bytes());
            },
            Instruction::Return => serialized.push(0x51),
            Instruction::Halt => serialized.push(0x52),
            Instruction::Nop => serialized.push(0x53),
            Instruction::RegisterToStack(reg) => {
                serialized.push(0x60);
                serialized.push(*reg);
            },
            Instruction::StackToRegister(idx, reg) => {
                serialized.push(0x61);
                serialized.extend_from_slice(&(*idx as u32).to_le_bytes());
                serialized.push(*reg);
            },
            Instruction::Print => serialized.push(0x70),
            Instruction::Println => serialized.push(0x71),
            Instruction::PrintStr(s) => {
                serialized.push(0x72);
                let len_bytes = (s.len() as u32).to_le_bytes();
                serialized.extend_from_slice(&len_bytes);
                serialized.extend_from_slice(s.as_bytes());
            },
            Instruction::StoreVar(idx) => {
                serialized.push(0x80);
                serialized.extend_from_slice(&idx.to_le_bytes());
            },
            Instruction::LoadVar(idx) => {
                serialized.push(0x81);
                serialized.extend_from_slice(&idx.to_le_bytes());
            },
            Instruction::MakeArray(count) => {
                serialized.push(0x90);
                serialized.extend_from_slice(&(*count as u32).to_le_bytes());
            },
            Instruction::ArrayGet => serialized.push(0x91),
            Instruction::ArraySet => serialized.push(0x92),
            Instruction::ArrayLength => serialized.push(0x93),
            Instruction::MakeStruct(count) => {
                serialized.push(0xA0);
                serialized.extend_from_slice(&(*count as u32).to_le_bytes());
            },
            Instruction::StructGet(field) => {
                serialized.push(0xA1);
                let len_bytes = (field.len() as u32).to_le_bytes();
                serialized.extend_from_slice(&len_bytes);
                serialized.extend_from_slice(field.as_bytes());
            },
            _ => {
                // 处理其他指令
                serialized.push(0xFF); // 未知指令标记
            }
        }
    }
    
    serialized
}

/// 调试脚本
fn debug_script(file: &PathBuf, verbose: bool) {
    let content = std::fs::read_to_string(file)
        .expect("无法读取文件");
    
    if verbose {
        println!("调试: {}", file.display());
    }
    
    let mut vm = VirtualMachine::new();
    // 注册标准库函数
    pipit_stdlib_integration::register_stdlib_functions(&mut vm);
    vm.load_script(&content);
    let _ = vm.execute();
}

fn debug_concurrent_engine() {
    // 创建并发引擎和计数器
    let engine = pipit_core::concurrent_engine::ConcurrentEngine::new(4);
    let counter = std::sync::Arc::new(pipit_core::concurrent_engine::ConcurrentCounter::new(0));
    let task_completed = std::sync::Arc::new(std::sync::Mutex::new(std::collections::HashSet::new()));
    
    // 提交一些任务
    println!("提交任务...");
    for i in 0..10 {
        let counter = counter.clone();
        let task_id = i;
        let task_completed = task_completed.clone();
        engine.submit_task(move || {
            println!("开始执行任务 {}", task_id);
            counter.increment();
            task_completed.lock().unwrap().insert(task_id);
            println!("完成任务 {}", task_id);
            std::thread::sleep(std::time::Duration::from_millis(100)); // 模拟工作
        });
    }
    
    // 添加一个额外的"哨兵"任务，确保所有任务都被处理
    engine.submit_task(move || {
        println!("执行哨兵任务");
        // 这个任务不做任何实际工作，只是为了确保队列被完全处理
    });
    
    // 等待任务完成
    println!("等待任务完成...");
    let start_time = std::time::Instant::now();
    let timeout = std::time::Duration::from_secs(5);
    
    loop {
        let count = counter.get();
        let completed_tasks: std::collections::HashSet<_> = task_completed.lock().unwrap().clone();
        println!("已完成任务数: {}, 具体任务: {:?}", count, completed_tasks);
        
        if count >= 10 {
            break;
        }
        
        if start_time.elapsed() > timeout {
            println!("超时，任务未完成。已完成任务数: {}", count);
            break;
        }
        
        std::thread::sleep(std::time::Duration::from_millis(200));
    }
    
    // 关闭引擎
    println!("关闭引擎...");
    engine.shutdown();
    println!("测试完成。最终计数器值: {}", counter.get());
}
